import sys
import re  # str.split
from PyQt5.QtWidgets import QApplication, QMainWindow, qApp
from functools import partial
import score_web

calc_str = ""
calc_type = 0
num1 = 0
num2 = 0
ans = 0


# start btn 主程序的开始
def click_start():
    print("开始识别")


# ------------------------------------------------------------------------------
# exchange btn 计算汇率
def conver(ui):
    input1 = ui.lineEdit_in.text()
    if input1 == "":
        ui.label.setText("Status: error")
        input1 = 0
    else:
        ui.lb_status.setText("Status: OK")
    input_num = float(input1)
    result = input_num / 6.7 if ui.btn_ch.isChecked() else input_num * 6.7
    ui.lineEdit_out.setText("{:.4f}".format(result))


# change btn 交换汇率
def btn_change(ui):
    if ui.btn_ch.isChecked():
        ui.lb_exh.setText("CNY -> USD")
    else:
        ui.lb_exh.setText("USD -> CNY")


# ------------------------------------------------------------------------------
# display calc process
def calc_view(ui, str1):
    global calc_str, ans
    if str1 == "clr":
        calc_str = ""
        ans = 0
        print("clear")
    elif str1 == "ans":
        calc_str = str(ans)
        print("ans")
    elif str1 == "bsp":
        calc_str = calc_str[:-1]
        print("Bsp")
    elif str1 == "calc":
        ans = ans
        print("case3:", ans)
    else:
        calc_str += str1
    ui.lineEdit_calc.setText(calc_str)
    ui.lineEdit_ans.setText("{:.4f}".format(ans))

# ------------------------------------------------------------------------------
# op_a 判定是否是高优先级
def priority(a, b):
    if (a == '+' or a == '-'):
        return False
    elif a == '*' or a == '/' or a == "%":
        return (b == '+' or b == '-')
    elif (a == "^"):
        return not (b == '^')
    return False

# 简单计算
def calc_num(num2, num1, op):
    # if str(num1).isnumeric() and str(num2).isnumeric():
    if True:
        num1 = float(num1)  # L
        num2 = float(num2)  # R
        operator = op
        result = {
            '+': lambda x: num1 + num2,
            '-': lambda x: num1 - num2,
            '*': lambda x: num1 * num2,
            '^': lambda x: num1**num2,
            '%': lambda x: num1 % num2,
            '/': lambda x: num1 / num2
        }[operator](x=operator)
        return result
    # else:
    #     ui.lb_calc.setText("请输入数字")
    #     return 0


# buttonx5
class btn_push():

    def PushAns(ui):
        global calc_str, ans
        calc_view(ui, "ans")
        calc_str = str(ans)
        # print("00")

    def Push0(ui):
        calc_view(ui, "0")

    def Push1(ui):
        calc_view(ui, "1")

    def Push2(ui):
        calc_view(ui, "2")

    def Push3(ui):
        calc_view(ui, "3")

    def Push4(ui):
        calc_view(ui, "4")

    def Push5(ui):
        calc_view(ui, "5")

    def Push6(ui):
        calc_view(ui, "6")

    def Push7(ui):
        calc_view(ui, "7")

    def Push8(ui):
        calc_view(ui, "8")

    def Push9(ui):
        calc_view(ui, "9")

    def PushDot(ui):
        calc_view(ui, ".")

    def PushClr(ui):
        calc_view(ui, "clr")

    # 低优先级
    def PushAdd(ui):
        calc_view(ui, "+")

    def PushSub(ui):
        calc_view(ui, "-")

    # 高优先级
    def PushMul(ui):
        calc_view(ui, "*")

    def PushDiv(ui):
        calc_view(ui, "/")

    def PushSq(ui):
        calc_view(ui, "^")

    def PushMod(ui):
        calc_view(ui, "%")

    def PushBsp(ui):
        calc_view(ui, "bsp")
        
    # 总计算 默认输入是一串无空格的字符
    def PushCalc(ui):
        global calc_str, ans
        op_list = []
        nums = []
        ops = []
        # calc_str = "6-5+5.*9+6-7/9"  # test
        # 健壮性
        if len(calc_str) == 0:
            calc_str = "0"
        if calc_str[0] == "-":
            # calc_str[0] == "." or
            # ui.lb_calc.setText("请在小数点前加数字")
            calc_str = "0" + calc_str
        # 存放数字
        opera_nums = re.split("\+|-|\*|/|\^|%", calc_str)
        print(opera_nums)
        opera_nums = list(filter(None, opera_nums))
        # 存放操作符8
        operators = re.sub("[\d]", "", calc_str)
        operators = re.sub("\.", "", operators)
        for i in range(len(operators)):
            op_list.append(operators[i])
        print("calc_str:", calc_str)
        print(opera_nums)
        print(op_list)
        # 循环计算
        loop = 0
        len_num = len(opera_nums)
        len_op = len(op_list)

        print(len_num, len_op)
        if len_num <= len_op:
            print("请注意表达式格式")
            calc_view(ui, "clr")
        else:
            # 若无输入
            if len_op == 0:
                ans = float(calc_str)
            else:
                while (True):
                    nums.append(opera_nums[loop])
                    # 若op栈非空
                    if len(ops) != 0:
                        # 高优先级op
                        if priority(op_list[loop], ops[-1]):
                            ops.append(op_list[loop])
                        # 出栈再放入新的op
                        else:
                            while (not len(ops) == 0) and not priority(
                                    op_list[loop], ops[-1]):
                                result = calc_num(nums.pop(), nums.pop(),
                                                  ops.pop())
                                nums.append(result)
                            ops.append(op_list[loop])
                    # 空栈
                    else:
                        ops.append(op_list[loop])
                    loop += 1
                    # 保证符号位索引安全
                    if loop == len_num - 1:
                        nums.append(opera_nums[loop])
                        break
                while (not len(ops) == 0):
                    result = calc_num(nums.pop(), nums.pop(), ops.pop())
                    nums.append(result)
                ans = nums[-1]
            calc_view(ui, "calc")


if __name__ == '__main__':
    app = QApplication(sys.argv)
    MainWindow = QMainWindow()
    ui = score_web.Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    # 添加按钮事件
    # ---------------------------------------------------#
    # exchange money
    ui.btn_ex.clicked.connect(partial(conver, ui))
    ui.btn_ch.clicked.connect(partial(btn_change, ui))
    # calc btn.clicked
    ui.btn_ans.clicked.connect(partial(btn_push.PushAns, ui))
    ui.btn_0.clicked.connect(partial(btn_push.Push0, ui))
    ui.btn_1.clicked.connect(partial(btn_push.Push1, ui))
    ui.btn_2.clicked.connect(partial(btn_push.Push2, ui))
    ui.btn_3.clicked.connect(partial(btn_push.Push3, ui))
    ui.btn_4.clicked.connect(partial(btn_push.Push4, ui))
    ui.btn_5.clicked.connect(partial(btn_push.Push5, ui))
    ui.btn_6.clicked.connect(partial(btn_push.Push6, ui))
    ui.btn_7.clicked.connect(partial(btn_push.Push7, ui))
    ui.btn_8.clicked.connect(partial(btn_push.Push8, ui))
    ui.btn_9.clicked.connect(partial(btn_push.Push9, ui))
    ui.btn_dot.clicked.connect(partial(btn_push.PushDot, ui))
    ui.btn_add.clicked.connect(partial(btn_push.PushAdd, ui))
    ui.btn_sub.clicked.connect(partial(btn_push.PushSub, ui))
    ui.btn_mul.clicked.connect(partial(btn_push.PushMul, ui))
    ui.btn_sq.clicked.connect(partial(btn_push.PushSq, ui))
    ui.btn_mod.clicked.connect(partial(btn_push.PushMod, ui))
    ui.btn_divide.clicked.connect(partial(btn_push.PushDiv, ui))
    ui.btn_clear.clicked.connect(partial(btn_push.PushClr, ui))
    ui.btn_bsp.clicked.connect(partial(btn_push.PushBsp, ui))
    ui.btn_calc.clicked.connect(partial(btn_push.PushCalc, ui))
    ui.action_3.triggered.connect(qApp.quit)
    sys.exit(app.exec_())
